package qeug.shsh.bpm.service.impl;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.huawei.shade.org.apache.commons.logging.Log;
import com.huawei.shade.org.apache.commons.logging.LogFactory;
import io.prestosql.jdbc.$internal.okhttp3.*;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.DispatchServiceHelper;
import kd.bos.servicehelper.operation.OperationServiceHelper;
import kd.data.idi.data.attachment.CheckMethodEnum;
import kd.data.idi.engine.attachment.Attachment;
import kd.data.idi.engine.attachment.AttachmentServiceFactory;
import kd.fi.er.common.constant.formproperties.mainbill.InvoiceEntry;
import org.springframework.util.Base64Utils;
import qeug.shsh.bpm.annotation.ThridSrevice;
import qeug.shsh.bpm.domain.*;
import qeug.shsh.bpm.service.BPMSrevice;
import qeug.shsh.bpm.utils.BPMUtil;
import qeug.shsh.helper.FacadeHelper;

import javax.xml.rpc.ServiceException;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.nio.charset.StandardCharsets;
import java.rmi.RemoteException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @projectName: qeug-cosmic-root-project
 * @package: qeug.shsh.bpm.service.impl
 * @className: BPMServiceImpl
 * @author: wenyx
 * @modifier: xuhh
 * @description: TODO
 * @date: 2023/11/3/16:21
 * @version: 2.0
 * 说明：差旅报销单，费用报销单，预算调整单提交推送BPM接口
 */
@ThridSrevice("BPMServiceImpl")
public class BPMServiceImpl implements BPMSrevice {

    private final static Log logger = LogFactory.getLog(BPMServiceImpl.class);//日志
    public static final String SYS = "CCS";

    private static final Map<String, String> VEHICLE_MAPPING = new HashMap<>();

    static {
        VEHICLE_MAPPING.put("1", "飞机");
        VEHICLE_MAPPING.put("2", "火车/高铁");
        VEHICLE_MAPPING.put("3", "汽车");
        VEHICLE_MAPPING.put("4", "轮船");
        VEHICLE_MAPPING.put("5", "其他工具");
    }

    //差旅报销单
    @Override
    public void tripReimburse(DynamicObject bos_tripReimburseBill) throws ServiceException, RemoteException, MalformedURLException {

        String bpm_url = System.getProperty("bpm.url");
        String basicAuthUserName = System.getProperty("po.user");//名字
        String basicAuthPassword = System.getProperty("po.password");//编码
        String domain = System.getProperty("domain.contextUrl");//IP地址

        //日志
        HashMap<String, Object> log = new HashMap<>();
        log.put("operationModule", "差旅报销单");
        log.put("url", bpm_url);
        log.put("user", basicAuthUserName);
        log.put("mode", "POST");
        log.put("action", "");
        log.put("opdate", new Date());
        Info info = new Info();
        BpmApplyInfo bpmApplyInfo = new BpmApplyInfo();
        ArrayList<FtEntry> ftEntrys = new ArrayList<>();//分摊明细
        ArrayList<XcEntry> xcEntrys = new ArrayList<>();//行程分录
        ArrayList<ClEntry> clEntries = new ArrayList<>();//差旅明细(行程分录的子分录)
        ArrayList<SkEntry> skEntrys = new ArrayList<>();//收款分录
        ArrayList<InvoiceEntrys> InvoiceEntrys = new ArrayList<>();//发票分录
        List<Attentrys> attEntrys = new ArrayList<Attentrys>();//附件分录
//        ArrayList<CjEntry> cjEntrys = new ArrayList<>();//冲借款分录
//        ArrayList<GlEntry> glEntrys = new ArrayList<>();//关联申请分录
        String number = bos_tripReimburseBill.getString("billno");//单据编码
        bpmApplyInfo.setNumber(number);
        DynamicObject applier = bos_tripReimburseBill.getDynamicObject("applier");//申请人
        if (applier != null) {
            String userNumber = applier.getString("number");
            String userName = applier.getString("name");
            bpmApplyInfo.setApplierNumber(userNumber);
            bpmApplyInfo.setApplierName(userName);
        }
        DynamicObject org = bos_tripReimburseBill.getDynamicObject("org");//申请部门
        if (org != null) {
            String orgNumber = org.getString("number");
            String orgName = org.getString("name");
            bpmApplyInfo.setAdminOrgNumber(orgNumber);
            bpmApplyInfo.setAdminOrgName(orgName);
        }
        Date applyDate = bos_tripReimburseBill.getDate("bizdate");//申请日期
        bpmApplyInfo.setBizdate(String.valueOf(applyDate));
        DynamicObject costCompany = bos_tripReimburseBill.getDynamicObject("costcompany");//费用承担公司
        if (costCompany != null) {
            String costCompanyNumber = costCompany.getString("number");
            String costCompanyName = costCompany.getString("name");
            bpmApplyInfo.setCompanyNumber(costCompanyNumber);
            bpmApplyInfo.setCompanyName(costCompanyName);
            bpmApplyInfo.setCostCompanyNumber(costCompanyNumber);
            bpmApplyInfo.setCostCompanyName(costCompanyName);
        }
        DynamicObject costDept = bos_tripReimburseBill.getDynamicObject("qeug_costdept");//一级承担部门
        if (costDept != null) {
            String costDeptNumber = costDept.getString("number");
            String costDeptName = costDept.getString("name");
            bpmApplyInfo.setCostdeptNumber(costDeptNumber);
            bpmApplyInfo.setCostdeptName(costDeptName);
        }
        DynamicObject travelCostcEnter = bos_tripReimburseBill.getDynamicObject("std_costcenter");//成本中心
        if (travelCostcEnter != null) {
            String travelCostcEnterName = travelCostcEnter.getString("name");
            String travelCostcEnterNumber = travelCostcEnter.getString("number");
            bpmApplyInfo.setTravelCostcEnterName(travelCostcEnterName);
            bpmApplyInfo.setTravelCostcEnterNumber(travelCostcEnterNumber);
        }
        DynamicObject tripType = bos_tripReimburseBill.getDynamicObject("triptype");//出差类型
        if (tripType != null) {
            String tripTypeName = tripType.getString("name");
            bpmApplyInfo.setTripTypeName(tripTypeName);
        }
        String description = bos_tripReimburseBill.getString("description");//事项说明
        bpmApplyInfo.setDescription(description);
        String budgetType = bos_tripReimburseBill.getString("qeug_budgetflag");//预算类型
        if ("0".equals(budgetType)) {
            budgetType = "预算外";
        } else if ("1".equals(budgetType)) {
            budgetType = "预算内";
        }
        bpmApplyInfo.setIsCyu(budgetType);
        boolean isTravelers = bos_tripReimburseBill.getBoolean("istravelers");//多出差人
        bpmApplyInfo.setistravelers(isTravelers);
        BigDecimal reimburseamount = bos_tripReimburseBill.getBigDecimal("amount");//报销金额（汇总）
        bpmApplyInfo.setReimburseAmount(reimburseamount);
/*        boolean isCurrency = bos_tripReimburseBill.getBoolean("iscurrency");//多币别
        String qeug_combofield = bos_tripReimburseBill.getString("qeug_combofield1");//报销标准
        if ("0".equals(qeug_combofield)) {
            qeug_combofield = "标准外";
        } else if ("1".equals(qeug_combofield)) {
            qeug_combofield = "标准内";
        }
        bpmApplyInfo.setIsCblx(qeug_combofield);*/
        boolean isBeforeShare = bos_tripReimburseBill.getBoolean("isbeforeshare");//费用分摊
        bpmApplyInfo.setisBeforeShare(String.valueOf(isBeforeShare));
        if (isBeforeShare) {
            String allocationRule = bos_tripReimburseBill.getString("sharerule");//分摊规则
            if ("orgrule".equals(allocationRule)) {
                allocationRule = "按部门分摊";
            } else if ("monthrule".equals(allocationRule)) {
                allocationRule = "按月分摊";
            } else if ("yearrule".equals(allocationRule)) {
                allocationRule = "按年分摊";
            } else if ("expenseitemrule".equals(allocationRule)) {
                allocationRule = "按费用项目分摊";
            }
            String method = bos_tripReimburseBill.getString("sharemethod");//分摊方法
            if ("rate".equals(method)) {
                method = "比例分摊";
            } else if ("avg".equals(method)) {
                method = "金额平均";
            } else if ("amount".equals(method)) {
                method = "金额分摊";
            }
            Date startingMonth = bos_tripReimburseBill.getDate("sharerule_startdate");//开始月份
            Date endMonth = bos_tripReimburseBill.getDate("sharerule_enddate");//结束月份
            bpmApplyInfo.setAllocationRule(allocationRule);
            bpmApplyInfo.setMethod(method);
            if (startingMonth != null && endMonth != null) {
                bpmApplyInfo.setStartingMonth(String.valueOf(startingMonth));
                bpmApplyInfo.setEndMonth(String.valueOf(endMonth));
            }
            StringBuilder departmentsBuilder = new StringBuilder();
            //分摊明细
            DynamicObjectCollection apportionCollection = bos_tripReimburseBill.getDynamicObjectCollection("expenseentryentity_rule");
            for (int i = 0; i < apportionCollection.size(); i++) {
                DynamicObject itineraryEntry = apportionCollection.get(i);
                FtEntry ftEntry = new FtEntry();
                DynamicObject ftCostCompany = itineraryEntry.getDynamicObject("entrycostcompany_orgrule");//费用承担公司
                if (ftCostCompany != null) {
                    String ftCostCompanyName = ftCostCompany.getString("name");
                    String ftCostCompanyNumber = ftCostCompany.getString("number");
                    ftEntry.setFtCostCompanyName(ftCostCompanyName);
                    ftEntry.setFtCostCompanyNumber(ftCostCompanyNumber);
                }
                DynamicObject ftCostDept = itineraryEntry.getDynamicObject("qeug_costdeptrule");//一级承担部门
                if (ftCostDept != null) {
                    String ftCostDeptName = ftCostDept.getString("name");
                    String ftCostDeptNumber = ftCostDept.getString("number");
                    if (i > 0) {
                        departmentsBuilder.append(","); // 在部门编号之间添加逗号和空格
                    }
                    departmentsBuilder.append(ftCostDeptNumber);
                    ftEntry.setFtCostDeptName(ftCostDeptName);
                    ftEntry.setFtCostDeptNumber(ftCostDeptNumber);
                }
                DynamicObject std_entrycostcenter_crule = itineraryEntry.getDynamicObject("std_entrycostcenter_crule");//成本中心
                if (std_entrycostcenter_crule != null) {
                    String costCenterName = std_entrycostcenter_crule.getString("name");
                    String costCenterNumber = std_entrycostcenter_crule.getString("number");
                    ftEntry.setCostCenterName(costCenterName);
                    ftEntry.setCostCenterNumber(costCenterNumber);
                }
                String amortizationRatio = itineraryEntry.getString("sharerate_comrule");//分摊比例（%）
                if (amortizationRatio != null) {
                    String formattedRatio = String.format("%.2f", Double.valueOf(amortizationRatio));
                    ftEntry.setAmortizationRatio(formattedRatio);
                }
                String remark = itineraryEntry.getString("shareremark");//备注
                ftEntry.setRemark(remark);
                BigDecimal assessedAmount = itineraryEntry.getBigDecimal("shareamount_comrule");//分摊金额
                ftEntry.setAssessedAmount(assessedAmount);
                Date month = itineraryEntry.getDate("entrymonth_monthrule");//月份
                if (month != null) {
                    ftEntry.setMonth(String.valueOf(month));
                }
                String waitingBankNumber = itineraryEntry.getString("qeug_sharewaitseq");//待摊行号
                ftEntry.setWaitingBankNumber(waitingBankNumber);

                ftEntrys.add(ftEntry);
            }
            String departments = departmentsBuilder.toString();
            bpmApplyInfo.setDepartments(departments);//分摊部门
        } else {
            bpmApplyInfo.setDepartments("");//分摊部门,没有分摊的时候分摊部门字段传空
        }

        //行程明细
        DynamicObjectCollection itineraryCollection = bos_tripReimburseBill.getDynamicObjectCollection("tripentry");
        for (int i = 0; i < itineraryCollection.size(); i++) {
            DynamicObject itineraryEntry = itineraryCollection.get(i);
            XcEntry xcEntry = new XcEntry();
            DynamicObject depart = itineraryEntry.getDynamicObject("from");//出发地
            String departName = depart.getString("name");
            DynamicObject destination = itineraryEntry.getDynamicObject("to");//目的地
            String destinationName = destination.getString("name");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH");
            Date startDate = itineraryEntry.getDate("startdate");//开始日期
            String formattedStartDate = sdf.format(startDate);
            Date endDate = itineraryEntry.getDate("enddate");//结束日期
            String formattedEndDate = sdf.format(endDate);
            DynamicObject tripEntryArea = itineraryEntry.getDynamicObject("tripentryarea");//出差地域
            if (tripEntryArea != null) {
                String tripEntryAreaName = tripEntryArea.getString("name");
                xcEntry.setBusinessTripArea(tripEntryAreaName);
            }
            String vehicles = itineraryEntry.getString("vehicles");//交通工具
            if (vehicles != null) {
                String vehicleNames = convertVehicleCodes(vehicles);
                xcEntry.setTransportation(vehicleNames);
            }
            DynamicObject entryCostDept = itineraryEntry.getDynamicObject("entrycostdept");//费用承担部门
            if (entryCostDept != null) {
                String entryCostDeptName = entryCostDept.getString("name");
                String entryCostDeptNumber = entryCostDept.getString("number");
                xcEntry.setEntryCostDeptName(entryCostDeptName);
                xcEntry.setEntryCostDeptNumber(entryCostDeptNumber);
            }
            DynamicObject tripExpenseItem = itineraryEntry.getDynamicObject("tripexpenseitem");//费用项目
            if (tripExpenseItem != null) {
                String tripExpenseItemNumber = tripExpenseItem.getString("number");
                String tripExpenseItemName = tripExpenseItem.getString("name");
                xcEntry.setCostNumber(tripExpenseItemNumber);
                xcEntry.setCostName(tripExpenseItemName);
            }
            //获取出差人的动态对象集合
            if (isTravelers) {
                DynamicObjectCollection travelersCollection = itineraryEntry.getDynamicObjectCollection("travelers");//出差人
                List<String> travelers = new ArrayList<>();
                for (int z = 0; z < travelersCollection.size(); z++) {
                    DynamicObject travelersEntry = travelersCollection.get(z);
                    if (travelersEntry != null) {
                        Long travelersId = travelersEntry.getLong(2);
                        DynamicObject businessTraveller = BusinessDataServiceHelper.loadSingle("bos_user", new QFilter("id", "=", travelersId).toArray());
                        String businessTravellerName = businessTraveller.getString("name");
                        travelers.add(businessTravellerName);
                    }
                    xcEntry.setBusinessTraveller(travelers.toString());
                }
            } else {
                DynamicObject businessTraveller = bos_tripReimburseBill.getDynamicObject("applier");//单出差人
                String businessTravellerName = businessTraveller.getString("name");
                xcEntry.setBusinessTraveller(businessTravellerName);
            }
            DynamicObject entryCurrency = itineraryEntry.getDynamicObject("tripcurrency");//币别
            if (entryCurrency != null) {
                String entryCurrencyName = entryCurrency.getString("name");
                xcEntry.setEntryCurrency(entryCurrencyName);
            }

            xcEntry.setDeparture(departName);
            xcEntry.setDestination(destinationName);
            StringBuilder tripDuration = new StringBuilder();
            tripDuration.append(formattedStartDate).append("~").append(formattedEndDate);
            xcEntry.setDuringTheTrip(String.valueOf(tripDuration));

            xcEntrys.add(xcEntry);

            int a = 0;
            //行程明细子分录：差旅明细
            DynamicObjectCollection travelCollection = itineraryEntry.getDynamicObjectCollection("entryentity");
            for (int j = 0; j < travelCollection.size(); j++) {
                DynamicObject travelEntry = travelCollection.get(j);
                ClEntry clEntry = new ClEntry();
                DynamicObject expenseItem = travelEntry.getDynamicObject("expenseitem");//差旅项目
                if (expenseItem != null) {
                    String expenseItemName = expenseItem.getString("name");
                    clEntry.setTripItemName(expenseItemName);
                    String expenseItemNumber = expenseItem.getString("number");
                    if ("010".equals(expenseItemNumber) || "011".equals(expenseItemNumber) || "012".equals(expenseItemNumber)) {
                        //误餐补贴传值
                        BigDecimal reimbursementAmount = travelEntry.getBigDecimal("orientryamount");//报销金额
                        clEntry.setAmount(reimbursementAmount);
                        clEntries.add(clEntry);
                    } else {
                        BigDecimal reimbursementAmount = travelEntry.getBigDecimal("orientryamount");//报销金额
                        BigDecimal amountRaw = travelEntry.getBigDecimal("entryamount");//报销金额(本位币)
                        BigDecimal rests = travelEntry.getBigDecimal("airportconstructionfee");//机场建设费及其他
                        String taxRate = travelEntry.getString("taxrate");//税率
                        String taxRates = String.format("%.2f", Double.parseDouble(taxRate));
                        String taxAmount = travelEntry.getString("taxamount");//税额
                        String taxAmounts = String.format("%.2f", Double.parseDouble(taxAmount));
                        BigDecimal noTaxAmount = travelEntry.getBigDecimal("notaxamount");//不含税金额
                        // 获取座位等级的动态对象集合
                        List<String> seatRades = new ArrayList<>();
                        DynamicObjectCollection seatRadeCollection = travelEntry.getDynamicObjectCollection("mulseatgrade");//座位等级
                        if (seatRadeCollection.size() > 0) {
                            for (int z = 0; z < seatRadeCollection.size(); z++) {
                                DynamicObject seatgRades = seatRadeCollection.get(z);
                                if (seatgRades != null) {
                                    Long seatgRadeId = seatgRades.getLong(2);
                                    DynamicObject seatgRade = BusinessDataServiceHelper.loadSingle("er_seatgradestd", new QFilter("id", "=", seatgRadeId).toArray());
                                    String seatgRadeName = seatgRade.getString("name");
                                    seatRades.add(seatgRadeName);
                                }
                            }
                            clEntry.setMulseatgrade(seatRades.toString());
                        }
                        String comment = travelEntry.getString("comment");//备注
                        String standardDays = travelEntry.getString("caldaycount");//标准天数
                        String formattedDays = String.format("%.0f", Double.parseDouble(standardDays));
                        String exceedDescription = travelEntry.getString("overdesc");//超标说明

                        clEntry.setTaxRate(taxRates);
                        clEntry.setTax(taxAmounts);
                        clEntry.setAmount(reimbursementAmount);
                        clEntry.setAmountRaw(amountRaw);
                        clEntry.setRests(rests);
                        clEntry.setNotaxamount(noTaxAmount);
                        clEntry.setComment(comment);
                        clEntry.setStandardDays(formattedDays);
                        if (exceedDescription != null) {
                            a++;
                            clEntry.setExceedDescription(exceedDescription);
                        }
                        clEntries.add(clEntry);
                    }
                }
            }
            if (a > 0) {
                //差旅明细中存在超标时，设置标准外
                bpmApplyInfo.setIsCblx("标准外");
            } else {
                bpmApplyInfo.setIsCblx("标准内");
            }

            //差旅明细合计分录
            BigDecimal oriEntryAmount = BigDecimal.ZERO;//报销金额合计
            BigDecimal entryAmount = BigDecimal.ZERO;//报销金额(本位币)合计
            BigDecimal airportconstructionfees = BigDecimal.ZERO;//机场建设费及其他合计
            BigDecimal taxRates1 = BigDecimal.ZERO;//税率合计
            BigDecimal taxAmounts1 = BigDecimal.ZERO;//税额合计
            BigDecimal noTaxAmounts = BigDecimal.ZERO;//不含税金额合计
            BigDecimal caldaycount = BigDecimal.ZERO;//标准天数合计
            for (DynamicObject travelEntry : travelCollection) {
                BigDecimal reimbursementAmount = travelEntry.getBigDecimal("orientryamount");//报销金额
                oriEntryAmount = oriEntryAmount.add(reimbursementAmount);
                BigDecimal amountRaw = travelEntry.getBigDecimal("entryamount");//报销金额(本位币)
                entryAmount = entryAmount.add(amountRaw);
                BigDecimal rests = travelEntry.getBigDecimal("airportconstructionfee");//机场建设费及其他
                airportconstructionfees = airportconstructionfees.add(rests);
                String taxRate = travelEntry.getString("taxrate");//税率
                String taxRates = String.format("%.2f", Double.parseDouble(taxRate));
                taxRates1 = taxRates1.add(new BigDecimal(taxRates));
                String taxAmount = travelEntry.getString("taxamount");//税额
                String taxAmounts = String.format("%.2f", Double.parseDouble(taxAmount));
                taxAmounts1 = taxAmounts1.add(new BigDecimal(taxAmounts));
                BigDecimal noTaxAmount = travelEntry.getBigDecimal("notaxamount");//不含税金额
                noTaxAmounts = noTaxAmounts.add(noTaxAmount);
                String standardDays = travelEntry.getString("caldaycount");//标准天数
                String formattedDays = String.format("%.0f", Double.parseDouble(standardDays));
                caldaycount = caldaycount.add(new BigDecimal(formattedDays));
            }
            ClEntry clEntry = new ClEntry();
            clEntry.setAmount(oriEntryAmount);
            clEntry.setAmountRaw(entryAmount);
            clEntry.setRests(airportconstructionfees);
            clEntry.setTaxRate(String.valueOf(taxRates1));
            clEntry.setTax(String.valueOf(taxAmounts1));
            clEntry.setNotaxamount(noTaxAmounts);
            clEntry.setStandardDays(String.valueOf(caldaycount));
            clEntries.add(clEntry);
        }

        //收款页签
        DynamicObjectCollection receiptCollection = bos_tripReimburseBill.getDynamicObjectCollection("accountentry");
        for (
                int i = 0; i < receiptCollection.size(); i++) {
            DynamicObject receiptEntry = receiptCollection.get(i);
            SkEntry skEntry = new SkEntry();
            DynamicObject paymode = receiptEntry.getDynamicObject("paymode");//支付方式
            if (paymode != null) {
                String paymodeName = paymode.getString("name");
                String paymodeNumber = paymode.getString("number");
                skEntry.setPayTpye(paymodeName);
                skEntry.setPayTpyeNumber(paymodeNumber);
            }
            String payertype = receiptEntry.getString("payertype");//收款人类型
            if (payertype.equals("bd_supplier")) {
                //收款人类型为供应商
                DynamicObject payee = receiptEntry.getDynamicObject("supplier");//收款人-供应商
                String payeeName = payee.getString("name");
                String payeeNumber = payee.getString("number");
                skEntry.setPayeeName(payeeName);
                skEntry.setPayeeNumber(payeeNumber);
            } else {
                //收款人类型为人员
                DynamicObject payee = receiptEntry.getDynamicObject("payer");//收款人-人员
                String payeeName = payee.getString("name");
                String payeeNumber = payee.getString("payer.number");
                skEntry.setPayeeName(payeeName);
                skEntry.setPayeeNumber(payeeNumber);
            }
            String payeeAccount = receiptEntry.getString("payeraccount");//银行账号
            String correspondentNumber = receiptEntry.getString("qeug_union");//联行号
            String accountTitle = receiptEntry.getString("payeraccountname");//账户名称
            DynamicObject openBankAccount = receiptEntry.getDynamicObject("payerbank");//开户银行
            if (openBankAccount != null) {
                String openBankAccountName = openBankAccount.getString("name");
                String openBankAccountNumber = openBankAccount.getString("number");
                skEntry.setBankName(openBankAccountName);
                skEntry.setBankNumber(openBankAccountNumber);
            }
            BigDecimal receiveAmount = receiptEntry.getBigDecimal("orireceiveamount");//收款金额
           /* if (isCurrency) {
                DynamicObject entryCurrency = receiptEntry.getDynamicObject("accountcurrency");//币别
                String entryCurrencyName = entryCurrency.getString("name");
                String exchanGerate = receiptEntry.getString("accexchangerate");//汇率
                BigDecimal attachmentsRaw = receiptEntry.getBigDecimal("receiveamount");//收款金额（本位币）
                skEntry.setEntryCurrency(entryCurrencyName);
                skEntry.setExchanGerate(exchanGerate);
                skEntry.setAttachmentsRaw(attachmentsRaw);
            }*/
            skEntry.setBankNum(payeeAccount);
            skEntry.setAccountTitle(accountTitle);
            skEntry.setInterbank(correspondentNumber);
            skEntry.setAttachments(receiveAmount);

            skEntrys.add(skEntry);
        }

        //发票分录
        DynamicObjectCollection invoiceCollection = bos_tripReimburseBill.getDynamicObjectCollection("invoiceentry");
        for (DynamicObject invoiceEntry : invoiceCollection) {
            InvoiceEntrys InvoiceEntry1 = new InvoiceEntrys();
            String serialNo = invoiceEntry.getString("serialno");//发票流水号
            String invoicegoodsname = invoiceEntry.getString("invoicegoodsname");//商品名称
            if (invoicegoodsname != null) {
                InvoiceEntry1.setInvoiceName(invoicegoodsname);//发票名称
            } else {
                String invoiceNo = invoiceEntry.getString("invoiceno");//发票号码
                InvoiceEntry1.setInvoiceName(invoiceNo);//发票名称
            }
            String downloadUrl = FacadeHelper.getDownloadUrl2(serialNo);
            String attUrl = domain + "/accessTokenLogin.do?access_token={}&redirect=" + downloadUrl;//推送下载地址

            InvoiceEntry1.setInvoiceUrls(attUrl);//下载地址

            InvoiceEntrys.add(InvoiceEntry1);
        }

        //附件分录
        long billId = bos_tripReimburseBill.getLong("id");
        List tripReimburse = AttachmentServiceFactory.getServiceInstance(CheckMethodEnum.CUSTOM).queryAttachmentInfo(billId, "er_tripreimbursebill", false);
        for (Object attachment : tripReimburse) {
            Attentrys attEntry = new Attentrys();
            Attachment bos_attachment = (Attachment) attachment;
            String url = bos_attachment.getUrl();
            String attUrl = domain + "/accessTokenLogin.do?access_token={}&redirect=" + url;
            String fileName = bos_attachment.getFileName();

            attEntry.setAttUrl(attUrl);
            attEntry.setAttName(fileName);

            attEntrys.add(attEntry);
        }
        bpmApplyInfo.setAttentrys(attEntrys);

        //人员信息
        DynamicObject creator = bos_tripReimburseBill.getDynamicObject("creator");//创建人
        String creatorNumber = creator.getString("number");

        bpmApplyInfo.setXcEntry(xcEntrys);
        bpmApplyInfo.setClEntry(clEntries);
        bpmApplyInfo.setFtEntry(ftEntrys);
        bpmApplyInfo.setSkEntry(skEntrys);
        bpmApplyInfo.setInvoiceEntrys(InvoiceEntrys);
        String strProcessName = SYS + "差旅报销单";

        BpmInfo bpmInfo = new BpmInfo();
        String summary = BPMUtil.getSummary(bos_tripReimburseBill, 2);
        bpmInfo.setSummary(summary);
        bpmInfo.setVariables(bpmApplyInfo);
        String json = JSONObject.toJSONString(bpmInfo);

        info.setnIncident(0);
        info.setStrProcessName(strProcessName);
        info.setStrLoginName(creatorNumber);
        info.setJson(json);
        String s = JSONObject.toJSONString(info);

        String basic = basicAuthUserName + ":" + basicAuthPassword;
        String encoding = Base64Utils.encodeToString(basic.getBytes(StandardCharsets.UTF_8));
        String send_standard = HttpRequest.post(bpm_url)
                .header("Authorization", "Basic " + encoding)
                .body(s)
                .execute().body();
        log.put("mainstring", s);
        log.put("responsebody", send_standard);
        logger.info("差旅报销单bpm回传信息：" + send_standard);

        JSONObject jsonObject = JSONObject.parseObject(send_standard);
        String incident = jsonObject.getString("incident");
        Integer integer = Integer.valueOf(incident);
        OperateOption option = OperateOption.create();
        if (integer > 0) { //成功，记录审批结果
            log.put("pdesc", "成功");
            FacadeHelper.apiLog(log);
            bos_tripReimburseBill.set("qeug_processinstance", incident);
            OperationServiceHelper.executeOperate("save", "er_tripreimbursebill", new DynamicObject[]{bos_tripReimburseBill}, option);
        } else {//失败的情况
            //撤销提交，记录日志
            log.put("pdesc", "失败");
            FacadeHelper.apiLog(log);
            OperationServiceHelper.executeOperate("unsubmit", "er_tripreimbursebill", new DynamicObject[]{bos_tripReimburseBill}, option);
            String error = jsonObject.getString("error");
            throw new RuntimeException("提交至BPM失败，异常原因:" + error);
        }

    }

    //费用报销单
    @Override
    public void dailyReimburse(DynamicObject bos_dailyReimburse) throws ServiceException, RemoteException, MalformedURLException {

        String bpm_url = System.getProperty("bpm.url");
        String basicAuthUserName = System.getProperty("po.user");//名字
        String basicAuthPassword = System.getProperty("po.password");//编码
        String domain = System.getProperty("domain.contextUrl");//IP地址

        //日志
        HashMap<String, Object> log = new HashMap<>();
        log.put("operationModule", "费用报销单");
        log.put("url", bpm_url);
        log.put("user", basicAuthUserName);
        log.put("mode", "POST");
        log.put("action", "");
        log.put("opdate", new Date());
        Info info = new Info();
        BpmApplyInfo bpmApplyInfo = new BpmApplyInfo();
        ArrayList<FyEntry> fyEntrys = new ArrayList<>();//费用分录
        ArrayList<FtEntry> ftEntrys = new ArrayList<>();//分摊明细
        ArrayList<GlEntry> glEntrys = new ArrayList<>();//关联申请分录
        ArrayList<SkEntry> skEntrys = new ArrayList<>();//收款分录
        ArrayList<InvoiceEntrys> InvoiceEntrys = new ArrayList<>();//发票分录
        List<Attentrys> attEntrys = new ArrayList<Attentrys>();//附件分录
//        ArrayList<CjEntry> cjEntrys = new ArrayList<>();//冲借款分录
        String number = bos_dailyReimburse.getString("billno");//单据编码
        DynamicObject applier = bos_dailyReimburse.getDynamicObject("applier");//申请人
        if (applier != null) {
            String userNumber = applier.getString("number");
            String userName = applier.getString("name");
            bpmApplyInfo.setApplierNumber(userNumber);
            bpmApplyInfo.setApplierName(userName);
        }
        DynamicObject org = bos_dailyReimburse.getDynamicObject("org");//申请部门
        if (org != null) {
            String orgNumber = org.getString("number");
            String orgName = org.getString("name");
            bpmApplyInfo.setAdminOrgNumber(orgNumber);
            bpmApplyInfo.setAdminOrgName(orgName);
        }
        DynamicObject company = bos_dailyReimburse.getDynamicObject("company");//申请公司
        if (company != null) {
            String companyNumber = company.getString("number");
            String companyName = company.getString("name");
            bpmApplyInfo.setCompanyNumber(companyNumber);
            bpmApplyInfo.setCompanyName(companyName);
        }
        Date applyDate = bos_dailyReimburse.getDate("bizdate");//申请日期
        DynamicObject costDept = bos_dailyReimburse.getDynamicObject("qeug_costdept");//一级承担部门
        if (costDept != null) {
            String costDeptNumber = costDept.getString("number");
            String costDeptName = costDept.getString("name");
            bpmApplyInfo.setCostdeptNumber(costDeptNumber);
            bpmApplyInfo.setCostdeptName(costDeptName);
        }
        DynamicObject travelCostcEnter = bos_dailyReimburse.getDynamicObject("std_costcenter");//成本中心
        if (travelCostcEnter != null) {
            String travelCostcEnterName = travelCostcEnter.getString("name");
            String travelCostcEnterNumber = travelCostcEnter.getString("number");
            bpmApplyInfo.setTravelCostcEnterName(travelCostcEnterName);
            bpmApplyInfo.setTravelCostcEnterNumber(travelCostcEnterNumber);
        }
        DynamicObject costCompany = bos_dailyReimburse.getDynamicObject("costcompany");//费用承担公司
        if (costCompany != null) {
            String costCompanyNumber = costCompany.getString("number");
            String costCompanyName = costCompany.getString("name");
            bpmApplyInfo.setCostCompanyNumber(costCompanyNumber);
            bpmApplyInfo.setCostCompanyName(costCompanyName);
        }
        DynamicObject tripType = bos_dailyReimburse.getDynamicObject("qeug_billtypefield");//单据类型
        if (tripType != null) {
            String tripTypeName = tripType.getString("name");
            String tripTypeNumber = tripType.getString("number");
            bpmApplyInfo.setBillTypeName(tripTypeName);
            bpmApplyInfo.setBillTypeNumber(tripTypeNumber);
        }
        String paymentType = bos_dailyReimburse.getString("qeug_paytype");//付款类别
        if ("1".equals(paymentType)) {
            paymentType = "应付";
        } else if ("2".equals(paymentType)) {
            paymentType = "预付";
        } else if ("3".equals(paymentType)) {
            paymentType = "事项";
        }
        String insideCause = bos_dailyReimburse.getString("description");//事由说明
        String budgetType = bos_dailyReimburse.getString("qeug_budgetflag");//预算类型
        if ("0".equals(budgetType)) {
            budgetType = "预算外";
        } else if ("1".equals(budgetType)) {
            budgetType = "预算内";
        }
        bpmApplyInfo.setIsCyu(budgetType);
        String qeug_combofield = bos_dailyReimburse.getString("qeug_combofield");//标准内外
        if ("0".equals(qeug_combofield)) {
            qeug_combofield = "标准外";
        } else if ("1".equals(qeug_combofield)) {
            qeug_combofield = "标准内";
        }
        bpmApplyInfo.setIsCb(qeug_combofield);
        BigDecimal reimburseAmount = bos_dailyReimburse.getBigDecimal("reimburseamount");//报销金额(汇总)

        bpmApplyInfo.setReimburseAmount(reimburseAmount);
        bpmApplyInfo.setNumber(number);
        bpmApplyInfo.setBizdate(String.valueOf(applyDate));
        bpmApplyInfo.setPayType(paymentType);
        bpmApplyInfo.setDescription(insideCause);

        boolean isCurrency = bos_dailyReimburse.getBoolean("iscurrency");//多币别
        bpmApplyInfo.setisCurrency(String.valueOf(isCurrency));
        boolean isMultiReimburser = bos_dailyReimburse.getBoolean("ismultireimburser");//多报销人
        bpmApplyInfo.setisMultiReimburser(isMultiReimburser);
        boolean isBeforeShare = bos_dailyReimburse.getBoolean("isbeforeshare");//费用分摊
        bpmApplyInfo.setisBeforeShare(String.valueOf(isBeforeShare));
        if (isBeforeShare) {
            String allocationRule = bos_dailyReimburse.getString("sharerule");//分摊规则
            if ("orgrule".equals(allocationRule)) {
                allocationRule = "按部门分摊";
            } else if ("monthrule".equals(allocationRule)) {
                allocationRule = "按月分摊";
            } else if ("yearrule".equals(allocationRule)) {
                allocationRule = "按年分摊";
            } else if ("expenseitemrule".equals(allocationRule)) {
                allocationRule = "按费用项目分摊";
            }
            String method = bos_dailyReimburse.getString("sharemethod");//分摊方法
            if ("rate".equals(method)) {
                method = "比例分摊";
            } else if ("avg".equals(method)) {
                method = "金额平均";
            } else if ("amount".equals(method)) {
                method = "金额分摊";
            }
            Date startingMonth = bos_dailyReimburse.getDate("sharerule_startdate");//开始月份
            Date endMonth = bos_dailyReimburse.getDate("sharerule_enddate");//结束月份
            bpmApplyInfo.setAllocationRule(allocationRule);
            bpmApplyInfo.setMethod(method);
            if (startingMonth != null && endMonth != null) {
                bpmApplyInfo.setStartingMonth(String.valueOf(startingMonth));
                bpmApplyInfo.setEndMonth(String.valueOf(endMonth));
            }
            StringBuilder departmentsBuilder = new StringBuilder();
            //分摊明细
            DynamicObjectCollection apportionCollection = bos_dailyReimburse.getDynamicObjectCollection("expenseentryentity_rule");
            for (int i = 0; i < apportionCollection.size(); i++) {
                DynamicObject itineraryEntry = apportionCollection.get(i);
                FtEntry ftEntry = new FtEntry();
                DynamicObject ftCostCompany = itineraryEntry.getDynamicObject("entrycostcompany_orgrule");//费用承担公司
                if (ftCostCompany != null) {
                    String ftCostCompanyName = ftCostCompany.getString("name");
                    String ftCostCompanyNumber = ftCostCompany.getString("number");
                    ftEntry.setFtCostCompanyName(ftCostCompanyName);
                    ftEntry.setFtCostCompanyNumber(ftCostCompanyNumber);
                }
                DynamicObject ftCostDept = itineraryEntry.getDynamicObject("qeug_costdeptrule");//一级承担部门
                if (ftCostDept != null) {
                    String ftCostDeptName = ftCostDept.getString("name");
                    String ftCostDeptNumber = ftCostDept.getString("number");
                    ftEntry.setFtCostDeptName(ftCostDeptName);
                    ftEntry.setFtCostDeptNumber(ftCostDeptNumber);
                    if (i > 0) {
                        departmentsBuilder.append(","); // 在部门编号之间添加逗号和空格
                    }
                    departmentsBuilder.append(ftCostDeptNumber);
                }
                DynamicObject std_entrycostcenter_crule = itineraryEntry.getDynamicObject("std_entrycostcenter_crule");//成本中心
                if (std_entrycostcenter_crule != null) {
                    String costCenterName = std_entrycostcenter_crule.getString("name");
                    String costCenterNumber = std_entrycostcenter_crule.getString("number");
                    ftEntry.setCostCenterName(costCenterName);
                    ftEntry.setCostCenterNumber(costCenterNumber);
                }
                String amortizationRatio = itineraryEntry.getString("sharerate_comrule");//分摊比例（%）
                if (amortizationRatio != null) {
                    String formattedRatio = String.format("%.2f", Double.valueOf(amortizationRatio));
                    ftEntry.setAmortizationRatio(formattedRatio);
                }
                String remark = itineraryEntry.getString("shareremark");//备注
                BigDecimal assessedAmount = itineraryEntry.getBigDecimal("shareamount_comrule");//分摊金额
                String waitingBankNumber = itineraryEntry.getString("sharewaitseq_comrule");//待摊行号
                Date month = itineraryEntry.getDate("entrymonth_monthrule");//月份
                if (month != null) {
                    ftEntry.setMonth(String.valueOf(month));
                }
                ftEntry.setRemark(remark);
                ftEntry.setAssessedAmount(assessedAmount);
                ftEntry.setWaitingBankNumber(waitingBankNumber);

                ftEntrys.add(ftEntry);
            }
            String departments = departmentsBuilder.toString();
            bpmApplyInfo.setDepartments(departments);//分摊部门
        } else {
            bpmApplyInfo.setDepartments("");//分摊部门,没有分摊的时候分摊部门字段传空
        }

        //费用明细
        DynamicObjectCollection expenselCollection = bos_dailyReimburse.getDynamicObjectCollection("expenseentryentity");
        for (int j = 0; j < expenselCollection.size(); j++) {
            DynamicObject expenseEntry = expenselCollection.get(j);
            FyEntry fyEntry = new FyEntry();
            DynamicObject entryCostDept = expenseEntry.getDynamicObject("entrycostdept");//费用承担部门(名称，编码
            if (entryCostDept != null) {
                String entryCostDeptName = entryCostDept.getString("name");
                String entryCostDeptNumber = entryCostDept.getString("number");
                fyEntry.setEntryCostDeptName(entryCostDeptName);
                fyEntry.setEntryCostDeptNumber(entryCostDeptNumber);
            }
            DynamicObject expenseType = expenseEntry.getDynamicObject("qeug_expensetype");//费用类型
            if (expenseType != null) {
                String expenseTypeName = expenseType.getString("fullname");
                fyEntry.setExpenseType(expenseTypeName);
            }
            DynamicObject expenseDetail = expenseEntry.getDynamicObject("qeug_expensedetail");//费用细项
            if (expenseDetail != null) {
                String expenseDetailName = expenseDetail.getString("fullname");
                fyEntry.setExpenseDetail(expenseDetailName);
            }
            DynamicObject expenseItem = expenseEntry.getDynamicObject("expenseitem");//费用名目（长名称，编码
            if (expenseItem != null) {
                String expenseItemName = expenseItem.getString("fullname");
                String expenseItemNumber = expenseItem.getString("number");
                fyEntry.setExpenseItemName(expenseItemName);
                fyEntry.setExpenseItemNumber(expenseItemNumber);
            }
            Date happenDate = expenseEntry.getDate("happendate");//费用发生日期
            String budgetAmount = expenseEntry.getString("qeug_budgetamount");//预算余额
            BigDecimal amount = expenseEntry.getBigDecimal("expenseamount");//报销金额
            String remark = expenseEntry.getString("remark");//备注
            if (isCurrency) {
                DynamicObject entryCurrency = expenseEntry.getDynamicObject("entrycurrency");//币别
                String entryCurrencyName = entryCurrency.getString("name");
                fyEntry.setEntryCurrency(entryCurrencyName);
            } else {
                fyEntry.setEntryCurrency("人民币");//多币别关闭时推送人民币
            }
            String exchanGerate = expenseEntry.getString("exchangerate");//汇率
            exchanGerate = String.format("%.2f", Double.parseDouble(exchanGerate));
            BigDecimal amountRaw = expenseEntry.getBigDecimal("currexpenseamount");//报销金额（本位币）
            String taxRate = expenseEntry.getString("taxrate");//税率
            String taxRates = String.format("%.2f", Double.parseDouble(taxRate));
            String taxAmount = expenseEntry.getString("taxamount");//税额
            String taxAmounts = String.format("%.2f", Double.parseDouble(taxAmount));
            BigDecimal noTaxAmount = expenseEntry.getBigDecimal("orientryamount");//不含税金额
            String invoiceno = expenseEntry.getString("invoiceno_entry");//发票号码
            String commodityName = expenseEntry.getString("expensegoodsname");//商品名称
            if (isMultiReimburser) {
                DynamicObject reimbursementApplicant = expenseEntry.getDynamicObject("reimburser");//报销人
                String reimbursementName = reimbursementApplicant.getString("name");
                String reimbursementNumber = reimbursementApplicant.getString("number");
                fyEntry.setReimbursementApplicant(reimbursementName);
                fyEntry.setReimbursementNumber(reimbursementNumber);
            }

            fyEntry.setTaxrate(taxRates);
            fyEntry.setTax(taxAmounts);
            fyEntry.setExchanGerate(exchanGerate);
            fyEntry.setAmountRaw(amountRaw);
            fyEntry.setHappendate(String.valueOf(happenDate));
            fyEntry.setBudgetAmount(budgetAmount);
            fyEntry.setAmount(amount);
            fyEntry.setComment(remark);
            fyEntry.setNotaxamount(noTaxAmount);
            fyEntry.setInvoiceno(invoiceno);
            fyEntry.setCommodityName(commodityName);

            fyEntrys.add(fyEntry);
        }
        //冲借款

        //关联申请
        DynamicObjectCollection associatedCollection = bos_dailyReimburse.getDynamicObjectCollection("writeoffapply");
        for (int i = 0; i < associatedCollection.size(); i++) {
            DynamicObject associatedEntry = associatedCollection.get(i);
            GlEntry glEntry = new GlEntry();
            String requestCode = associatedEntry.getString("applybillno");//申请单号
            DynamicObject glCostCompany = associatedEntry.getDynamicObject("applycostcompany");//费用承担公司
            if (glCostCompany != null) {
                String glCostCompanyName = glCostCompany.getString("name");
                String glCostCompanyNumber = glCostCompany.getString("number");
                glEntry.setGlCostCompanyName(glCostCompanyName);
                glEntry.setGlCostCompanyNumber(glCostCompanyNumber);
            }
            String glApplierName = associatedEntry.getString("applyperson");//申请人
            DynamicObject glCostDept = associatedEntry.getDynamicObject("applycostdept");//费用承担部门
            if (glCostDept != null) {
                String glCostDeptName = glCostDept.getString("name");
                String glCostDeptNumber = glCostDept.getString("number");
                glEntry.setGlCostDeptName(glCostDeptName);
                glEntry.setGlCostDeptNumber(glCostDeptNumber);
            }
            Date glBizDate = associatedEntry.getDate("applybilldate");//申请日期
            String glDescription = associatedEntry.getString("applydescription");//事由
            BigDecimal reimbursableAmount = associatedEntry.getBigDecimal("expebalanceamount");//可报销金额（本位币）
            BigDecimal glAmountWrittenOff = associatedEntry.getBigDecimal("reimbursedcurramount");//冲销金额（本位币）

            glEntry.setRequestCode(requestCode);
            glEntry.setApplier(glApplierName);
            glEntry.setGlBizDate(String.valueOf(glBizDate));
            glEntry.setGlDescription(glDescription);
            glEntry.setReimbursableAmount(reimbursableAmount);
            glEntry.setGlAmountWrittenOff(glAmountWrittenOff);

            glEntrys.add(glEntry);
        }

        //收款页签
        DynamicObjectCollection receiptCollection = bos_dailyReimburse.getDynamicObjectCollection("accountentry");
        for (int i = 0; i < receiptCollection.size(); i++) {
            DynamicObject receiptEntry = receiptCollection.get(i);
            SkEntry skEntry = new SkEntry();
            DynamicObject paymode = receiptEntry.getDynamicObject("paymode");//支付方式
            if (paymode != null) {
                String paymodeName = paymode.getString("name");
                String paymodeNumber = paymode.getString("number");
                skEntry.setPayTpye(paymodeName);
                skEntry.setPayTpyeNumber(paymodeNumber);
            }
            String payertype = receiptEntry.getString("payertype");//收款人类型
            if (payertype.equals("bd_supplier")) {
                //收款人类型为供应商
                DynamicObject payee = receiptEntry.getDynamicObject("supplier");//收款人-供应商
                String payeeName = payee.getString("name");
                String payeeNumber = payee.getString("number");
                skEntry.setPayeeName(payeeName);
                skEntry.setPayeeNumber(payeeNumber);
            } else {
                //收款人类型为人员
                DynamicObject payee = receiptEntry.getDynamicObject("payer");//收款人-人员
                String payeeName = payee.getString("name");
                String payeeNumber = payee.getString("payer.number");
                skEntry.setPayeeName(payeeName);
                skEntry.setPayeeNumber(payeeNumber);
            }
            String payeeAccount = receiptEntry.getString("payeraccount");//银行账号
            String correspondentNumber = receiptEntry.getString("qeug_union");//联行号
            String accountTitle = receiptEntry.getString("payeraccountname");//账户名称
            DynamicObject openBankAccount = receiptEntry.getDynamicObject("payerbank");//开户银行
            if (openBankAccount != null) {
                String openBankAccountName = openBankAccount.getString("name");
                String openBankAccountNumber = openBankAccount.getString("number");
                skEntry.setBankName(openBankAccountName);
                skEntry.setBankNumber(openBankAccountNumber);
            }
            BigDecimal receiveAmount = receiptEntry.getBigDecimal("orireceiveamount");//收款金额
            if (isCurrency) {
                DynamicObject entryCurrency = receiptEntry.getDynamicObject("accountcurrency");//币别
                String entryCurrencyName = entryCurrency.getString("name");
                skEntry.setEntryCurrency(entryCurrencyName);
            } else {
                skEntry.setEntryCurrency("人民币");//多币别关闭时推送人民币
            }
            String exchanGerate = receiptEntry.getString("accexchangerate");//汇率
            exchanGerate = String.format("%.2f", Double.parseDouble(exchanGerate));
            BigDecimal attachmentsRaw = receiptEntry.getBigDecimal("receiveamount");//收款金额（本位币）

            skEntry.setExchanGerate(exchanGerate);
            skEntry.setAttachmentsRaw(attachmentsRaw);
            skEntry.setBankNum(payeeAccount);
            skEntry.setAccountTitle(accountTitle);
            skEntry.setInterbank(correspondentNumber);
            skEntry.setAttachments(receiveAmount);

            skEntrys.add(skEntry);
        }

        //发票分录
        DynamicObjectCollection invoiceCollection = bos_dailyReimburse.getDynamicObjectCollection("invoiceentry");
        for (DynamicObject invoiceEntry : invoiceCollection) {
            InvoiceEntrys InvoiceEntry1 = new InvoiceEntrys();
            String serialNo = invoiceEntry.getString("serialno");//发票流水号
            String invoicegoodsname = invoiceEntry.getString("invoicegoodsname");//商品名称
            if (invoicegoodsname != null) {
                InvoiceEntry1.setInvoiceName(invoicegoodsname);//发票名称
            } else {
                String invoiceNo = invoiceEntry.getString("invoiceno");//发票号码
                InvoiceEntry1.setInvoiceName(invoiceNo);//发票名称
            }
            String downloadUrl = FacadeHelper.getDownloadUrl2(serialNo);
            String attUrl = domain + "/accessTokenLogin.do?access_token={}&redirect=" + downloadUrl;//推送下载地址

            InvoiceEntry1.setInvoiceUrls(attUrl);//下载地址

            InvoiceEntrys.add(InvoiceEntry1);
        }

        //附件分录
        long billId = bos_dailyReimburse.getLong("id");
        List tripReimburse = AttachmentServiceFactory.getServiceInstance(CheckMethodEnum.CUSTOM).queryAttachmentInfo(billId, "er_dailyreimbursebill", false);
        for (Object attachment : tripReimburse) {
            Attentrys attEntry = new Attentrys();
            Attachment bos_attachment = (Attachment) attachment;
            String url = bos_attachment.getUrl();
            String attUrl = domain + "/accessTokenLogin.do?access_token={}&redirect=" + url;
            String fileName = bos_attachment.getFileName();

            attEntry.setAttUrl(attUrl);
            attEntry.setAttName(fileName);

            attEntrys.add(attEntry);
        }

        //人员信息
        DynamicObject creator = bos_dailyReimburse.getDynamicObject("creator");//创建人
        String creatorNumber = creator.getString("number");

        //拼接Json
        bpmApplyInfo.setAttentrys(attEntrys);
        bpmApplyInfo.setFyEntry(fyEntrys);
        bpmApplyInfo.setSkEntry(skEntrys);
        bpmApplyInfo.setFtEntry(ftEntrys);
        bpmApplyInfo.setGlEntry(glEntrys);
        bpmApplyInfo.setInvoiceEntrys(InvoiceEntrys);
        String strProcessName = SYS + "费用报销单";

        BpmInfo bpmInfo = new BpmInfo();
        String summary = BPMUtil.getSummary(bos_dailyReimburse, 3);
        bpmInfo.setSummary(summary);
        bpmInfo.setVariables(bpmApplyInfo);
        String json = JSONObject.toJSONString(bpmInfo);

        info.setnIncident(0);
        info.setStrProcessName(strProcessName);
        info.setStrLoginName(creatorNumber);
        info.setJson(json);
        String s = JSONObject.toJSONString(info);

        String basic = basicAuthUserName + ":" + basicAuthPassword;
        String encoding = Base64Utils.encodeToString(basic.getBytes(StandardCharsets.UTF_8));
        String send_standard = HttpRequest.post(bpm_url)
                .header("Authorization", "Basic " + encoding)
                .body(s)
                .execute().body();
        log.put("mainstring", s);
        log.put("responsebody", send_standard);
        logger.info("费用报销单bpm回传信息：" + send_standard);

        JSONObject jsonObject = JSONObject.parseObject(send_standard);
        String incident = jsonObject.getString("incident");
        Integer integer = Integer.valueOf(incident);
        OperateOption option = OperateOption.create();
        if (integer > 0) { //成功，记录审批结果
            log.put("pdesc", "成功");
            FacadeHelper.apiLog(log);
            bos_dailyReimburse.set("qeug_processinstance", incident);
            OperationServiceHelper.executeOperate("save", "er_dailyreimbursebill", new DynamicObject[]{bos_dailyReimburse}, option);
        } else {//失败的情况
            //撤销提交，记录日志
            log.put("pdesc", "失败");
            FacadeHelper.apiLog(log);
            OperationServiceHelper.executeOperate("unsubmit", "er_dailyreimbursebill", new DynamicObject[]{bos_dailyReimburse}, option);
            String error = jsonObject.getString("error");
            throw new RuntimeException("提交至BPM失败，异常原因:" + error);
        }
    }

    //预算调整单
    @Override
    public void adjustBill(DynamicObject bgm_adjustBill) throws ServiceException, RemoteException, MalformedURLException {

        String bpm_url = System.getProperty("bpm.url");
        String basicAuthUserName = System.getProperty("po.user");//名字
        String basicAuthPassword = System.getProperty("po.password");//编码

        //日志
        HashMap<String, Object> log = new HashMap<>();
        log.put("operationModule", "预算调整单");
        log.put("url", bpm_url);
        log.put("user", basicAuthUserName);
        log.put("mode", "POST");
        log.put("action", "");
        log.put("opdate", new Date());
        Info info = new Info();
        BpmApplyInfo bpmApplyInfo = new BpmApplyInfo();
        ArrayList<AdjustEntry> adjustEntrys = new ArrayList<>();//调整明细
        String number = bgm_adjustBill.getString("billno");//单据编码
        DynamicObject applier = bgm_adjustBill.getDynamicObject("applier");//申请人
        if (applier != null) {
            String userNumber = applier.getString("number");
            String userName = applier.getString("name");
            bpmApplyInfo.setApplierNumber(userNumber);
            bpmApplyInfo.setApplierName(userName);
            info.setStrLoginName(userNumber);
        }
        DynamicObject department = bgm_adjustBill.getDynamicObject("qeug_costdept");//一级承担部门
        if (department != null) {
            String departmentNumber = department.getString("number");
            String departmentName = department.getString("name");
            bpmApplyInfo.setAdminOrgNumber(departmentNumber);
            bpmApplyInfo.setAdminOrgName(departmentName);
        }
        DynamicObject company = bgm_adjustBill.getDynamicObject("qeug_company");//公司
        if (company != null) {
            String companyNumber = company.getString("number");
            String companyName = company.getString("name");
            bpmApplyInfo.setCompanyNumber(companyNumber);
            bpmApplyInfo.setCompanyName(companyName);
        }
        Date bizDate = bgm_adjustBill.getDate("applydate");//申请日期
        DynamicObject budgetSystem = bgm_adjustBill.getDynamicObject("model");//预算体系
        if (budgetSystem != null) {
            String budgetSystemName = budgetSystem.getString("name");
            bpmApplyInfo.setBudgetSystem(budgetSystemName);
        }
        DynamicObject businessModel = bgm_adjustBill.getDynamicObject("bizmodel");//业务模板
        if (businessModel != null) {
            String businessModelName = businessModel.getString("name");
            bpmApplyInfo.setBusinessModel(businessModelName);
        }
        DynamicObject adjustmentRule = bgm_adjustBill.getDynamicObject("adjustrule");//调整规则
        if (adjustmentRule != null) {
            String adjustmentRuleName = adjustmentRule.getString("rulename");
            bpmApplyInfo.setAdjustmentRule(adjustmentRuleName);
        }
        DynamicObject dataType = bgm_adjustBill.getDynamicObject("datatype");//数据类型
        if (dataType != null) {
            String dataTypeName = dataType.getString("name");
            bpmApplyInfo.setDataType(dataTypeName);
        }
        //获取预算期间的动态对象集合
        List<String> budgetPeriodNames = new ArrayList<>(); // 用于存储budgetPeriodName的集合
        DynamicObjectCollection budgetPeriodCollection = bgm_adjustBill.getDynamicObjectCollection("budgetperiods");//预算期间
        for (int z = 0; z < budgetPeriodCollection.size(); z++) {
            DynamicObject budgetPeriodEntry = budgetPeriodCollection.get(z);
            if (budgetPeriodEntry != null) {
                Long budgetPeriodId = budgetPeriodEntry.getLong(2);
                DynamicObject budgetPeriod = BusinessDataServiceHelper.loadSingle("epm_bperiodmembertree", new QFilter("id", "=", budgetPeriodId).toArray());
                String budgetPeriodName = budgetPeriod.getString("name");
                budgetPeriodNames.add(budgetPeriodName); // 将budgetPeriodName添加到集合中
            }
        }
//        String budgetPeriodStr = budgetPeriodNames.isEmpty() ? "" : budgetPeriodNames.get(0); // 取第一个预算期间名称作为字符串
        String budgetPeriodStr = String.join(",", budgetPeriodNames); // 将列表转换为字符串，使用逗号分隔
        DynamicObject edition = bgm_adjustBill.getDynamicObject("version");//版本
        if (edition != null) {
            String editionName = edition.getString("name");
            bpmApplyInfo.setEdition(editionName);
        }
        DynamicObject variationType = bgm_adjustBill.getDynamicObject("changetype");//变动类型
        if (variationType != null) {
            String variationTypeName = variationType.getString("name");
            bpmApplyInfo.setVariationType(variationTypeName);
        }
        DynamicObject currency = bgm_adjustBill.getDynamicObject("currency");//币别
        if (currency != null) {
            String currencyName = currency.getString("name");
            bpmApplyInfo.setcurrency(currencyName);
        }
        String adjustRenson = bgm_adjustBill.getString("adjustreason");//调整原因

        bpmApplyInfo.setNumber(number);
        bpmApplyInfo.setBizdate(String.valueOf(bizDate));
        bpmApplyInfo.setBudgetPeriod(budgetPeriodStr);
        bpmApplyInfo.setAdjustRenson(adjustRenson);
        bpmApplyInfo.setDepartments("");//分摊部门,没有分摊的时候分摊部门字段传空

        //调整明细
        DynamicObjectCollection adjustCollection = bgm_adjustBill.getDynamicObjectCollection("adjdetailentity");
        for (int i = 0; i < adjustCollection.size(); i++) {
            DynamicObject adjustEntry = adjustCollection.get(i);
            AdjustEntry adjustsEntry = new AdjustEntry();
            DynamicObject budgetOrg = adjustEntry.getDynamicObject("entity");//预算组织
            if (budgetOrg != null) {
                String budgetOrganization = budgetOrg.getString("number");
                String BudgetOrgName = budgetOrg.getString("name");
                adjustsEntry.setBudgetOrgNumebr(budgetOrganization);
                adjustsEntry.setBudgetOrgName(BudgetOrgName);
            }
            DynamicObject budgetAccount = adjustEntry.getDynamicObject("account");//预算科目
            if (budgetAccount != null) {
                String budgetAccountName = budgetAccount.getString("name");
                String budgetAccountNumber = budgetAccount.getString("number");
                adjustsEntry.setBudgetAccount(budgetAccountName);
                adjustsEntry.setBudgetAccountNum(budgetAccountNumber);
            }
            DynamicObject measure = adjustEntry.getDynamicObject("metric");//度量
            if (measure != null) {
                String measureName = measure.getString("name");
                adjustsEntry.setMeasure(measureName);
            }
            DynamicObject budgetPeriod = adjustEntry.getDynamicObject("budgetperiod");//预算期间
            if (budgetPeriod != null) {
                String budgetPeriodName = budgetPeriod.getString("name");
                adjustsEntry.setBudgetPeriod(budgetPeriodName);
            }
            BigDecimal estimatedAmount = adjustEntry.getBigDecimal("budgetdata");//预算数
            BigDecimal adjustedNumber = adjustEntry.getBigDecimal("adjustdata");//调整数
            String adjexplain = adjustEntry.getString("adjexplain");//调整说明
            BigDecimal adjustmentBe = adjustEntry.getBigDecimal("finaldata");//调整后
            String budgetperiod = adjustEntry.getString("budgetperiod.name");//预算期间

            adjustsEntry.setEstimatedAmount(estimatedAmount);
            adjustsEntry.setAdjustedNumber(adjustedNumber);
            adjustsEntry.setAdjexplain(adjexplain);
            adjustsEntry.setAdjustmentBe(adjustmentBe);
            adjustsEntry.setBudgetPeriod(budgetperiod);

            adjustEntrys.add(adjustsEntry);
        }
        //附件分录
        long billId = bgm_adjustBill.getLong("id");
        String domain = System.getProperty("domain.contextUrl");
        List tripReimburse = AttachmentServiceFactory.getServiceInstance(CheckMethodEnum.CUSTOM).queryAttachmentInfo(billId, "bgm_adjustbill", false);
        List<Attentrys> attEntrys = new ArrayList<Attentrys>();
        for (Object attachment : tripReimburse) {
            Attentrys attEntry = new Attentrys();
            Attachment bos_attachment = (Attachment) attachment;
            String url = bos_attachment.getUrl();
            String attUrl = domain + "/accessTokenLogin.do?access_token={}&redirect=" + url;
            String fileName = bos_attachment.getFileName();

            attEntry.setAttUrl(attUrl);
            attEntry.setAttName(fileName);

            attEntrys.add(attEntry);
        }
        bpmApplyInfo.setAttentrys(attEntrys);

        //人员信息（预算调整单没有创建人）取用申请人
//        DynamicObject creator = bgm_adjustBill.getDynamicObject("creator");//创建人
//        String creatorNumber = creator.getString("number");

        //拼接Json
        bpmApplyInfo.setAdjustEntry(adjustEntrys);
        String strProcessName = SYS + "预算调整流程";

        BpmInfo bpmInfo = new BpmInfo();
        String summary = BPMUtil.getSummary(bgm_adjustBill, 0);
        bpmInfo.setSummary(summary);
        bpmInfo.setVariables(bpmApplyInfo);
        String json = JSONObject.toJSONString(bpmInfo);

        info.setnIncident(0);
        info.setStrProcessName(strProcessName);
        info.setJson(json);
        String s = JSONObject.toJSONString(info);

        String basic = basicAuthUserName + ":" + basicAuthPassword;
        String encoding = Base64Utils.encodeToString(basic.getBytes(StandardCharsets.UTF_8));
        String send_standard = HttpRequest.post(bpm_url)
                .header("Authorization", "Basic " + encoding)
                .body(s)
                .execute().body();
        log.put("mainstring", s);
        log.put("responsebody", send_standard);
        logger.info("预算调整单bpm回传信息：" + send_standard);

        JSONObject jsonObject = JSONObject.parseObject(send_standard);
        String incident = jsonObject.getString("incident");
        Integer integer = Integer.valueOf(incident);
        OperateOption option = OperateOption.create();
        if (integer > 0) { //成功，记录审批结果
            log.put("pdesc", "成功");
            FacadeHelper.apiLog(log);
            bgm_adjustBill.set("qeug_processinstance", incident);
//            OperationServiceHelper.executeOperate("modify", "bgm_adjustbill", new DynamicObject[]{bgm_adjustBill}, option);
            OperationServiceHelper.executeOperate("save", "bgm_adjustbill", new DynamicObject[]{bgm_adjustBill}, option);
        } else {//失败的情况
            //撤销提交，记录日志
            log.put("pdesc", "失败");
            FacadeHelper.apiLog(log);
            OperationServiceHelper.executeOperate("unsubmit", "bgm_adjustbill", new DynamicObject[]{bgm_adjustBill}, option);
            String error = jsonObject.getString("error");
            throw new RuntimeException("提交至BPM失败，异常原因:" + error);
        }
    }

    // 处理交通工具的转换方法
    public static String convertVehicleCodes(String codes) {
        if (codes == null || codes.isEmpty()) return "";
        return Arrays.stream(codes.split(","))
                .map(String::trim)
                .filter(VEHICLE_MAPPING::containsKey)
                .map(VEHICLE_MAPPING::get)
                .collect(Collectors.joining(","));
    }
}

